import ResponsiveObserve from '@/utils/responsiveObserve';
import classNames from 'classnames';
import React, { useEffect, useMemo } from 'react';
import RowContext from './RowContext';
import { Breakpoint, Gutter, ScreenMap, YmRowProps } from './interface';

// 数组顺序不能变，从大到小
export const responsiveArray: Breakpoint[] = [
  'xxl',
  'xl',
  'lg',
  'md',
  'sm',
  'xs',
];

const Row: React.FC<YmRowProps> = (props) => {
  const {
    gutter,
    align,
    justify,
    wrap,
    className,
    style,
    children,
    prefixCls = 'ym-row',
    ...others
  } = props;
  const [screens, setScreens] = React.useState<ScreenMap>({
    xs: true,
    sm: true,
    md: true,
    lg: true,
    xl: true,
    xxl: true,
  });
  // to save screens info when responsiveObserve callback had been call
  const [curScreens, setCurScreens] = React.useState<ScreenMap>({
    xs: false,
    sm: false,
    md: false,
    lg: false,
    xl: false,
    xxl: false,
  });

  const clacMergeAlignOrJustify = (
    oriProp: YmRowProps['align'] | YmRowProps['justify'],
    screen: ScreenMap,
  ) => {
    if (typeof oriProp !== 'object') {
      return oriProp;
    }
    // ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
    for (let i = 0; i < responsiveArray.length; i++) {
      const breakpoint: Breakpoint = responsiveArray[i];
      // if do not match, do nothing
      if (!screen[breakpoint]) continue;
      const curVal = oriProp[breakpoint];
      if (curVal !== undefined && curVal !== null) {
        return curVal;
      }
    }
  };

  const getGutterArray = (gutter: YmRowProps['gutter'], screen: ScreenMap) => {
    const results: [number | undefined, number | undefined] = [
      undefined,
      undefined,
    ];
    const normalizedGutter = Array.isArray(gutter)
      ? gutter
      : [gutter, undefined];
    normalizedGutter.forEach((g, index) => {
      if (typeof g === 'object') {
        for (let i = 0; i < responsiveArray.length; i++) {
          const breakpoint: Breakpoint = responsiveArray[i];
          if (
            screens[breakpoint] &&
            g[breakpoint] !== undefined &&
            g[breakpoint] !== null
          ) {
            results[index] = g[breakpoint] as number;
            break;
          }
        }
      } else {
        results[index] = g;
      }
    });
    return results;
  };

  // 间距参数 { xs: 'middle'} => middle
  const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>(gutter);

  // 垂直对齐方式 { xs: 'center'} => center
  // const mergeAlign = useMergePropByScreen(align, curScreens);
  const mergeAlign = useMemo(
    () => clacMergeAlignOrJustify(align, curScreens),
    [align, curScreens],
  );

  // 水平排列方式
  const mergeJustify = useMemo(
    () => clacMergeAlignOrJustify(justify, curScreens),
    [justify, curScreens],
  );

  // [水平,垂直] 间距
  const gutterArray: [number | undefined, number | undefined] = useMemo(
    () => getGutterArray(gutter, curScreens),
    [gutter, curScreens],
  );

  const rowStyle: React.CSSProperties = {};
  const horizontalGutter =
    gutterArray[0] !== null && (gutterArray[0] as any) > 0
      ? (gutterArray[0] as any) / -2
      : undefined;
  const verticalGutter =
    gutterArray[1] !== null && (gutterArray[1] as any) > 0
      ? (gutterArray[1] as any)
      : undefined;
  if (verticalGutter) {
    rowStyle.rowGap = verticalGutter;
  }

  if (horizontalGutter) {
    rowStyle.marginLeft = horizontalGutter;
    rowStyle.marginRight = horizontalGutter;
  }

  useEffect(() => {
    // 媒体查询--事件监听
    const token = ResponsiveObserve.subscribe((screen) => {
      // console.log('--row--screen---:', screen);
      setCurScreens(screen);
      const currentGutter = gutterRef.current || 0;
      if (
        (!Array.isArray(currentGutter) && typeof currentGutter === 'object') ||
        (Array.isArray(currentGutter) &&
          (typeof currentGutter[0] === 'object' ||
            typeof currentGutter[1] === 'object'))
      ) {
        setScreens(screen);
      }
    });
    return () => ResponsiveObserve.unsubscribe(token);
  }, []);

  const classes = classNames(
    prefixCls,
    {
      [`${prefixCls}-no-wrap`]: wrap === false,
      [`${prefixCls}-${mergeJustify}`]: mergeJustify,
      [`${prefixCls}-${mergeAlign}`]: mergeAlign,
    },
    className,
  );

  return (
    <RowContext.Provider value={{ gutter: gutterArray, wrap }}>
      <div {...others} className={classes} style={{ ...rowStyle, ...style }}>
        {children}
      </div>
    </RowContext.Provider>
  );
};

export default Row;
